Duncan Matheson

Role: Software

To Do List:
/**
* Basic weighing methods
*/
 
//Includes
#include <p18f452.h>
 
//Prototypes
void initialiseADConverter();
int getADValue();
float convert_unit(float mass, int inputUnit, int outputUnit);
 
//#defines
#define GRAMS 0
#define OUNCES 1
 
//Global variables
//massConvertLookup[i][j] is converting unit i to unit j
float[][] massConvertLookup = {{1.0, 28.349523125},
                      {0.0352739619, 1.0}};
/* y = mx + b, where y is the result mass in unit i, x is the voltage,
m is the gradient voltageToMass[i][0], b is the y-intercept voltageToMass[i][1]. */
float[][] voltageToMassEquation = {{285.48, -34.235},
                   {10.07,  -1.208}};
 
#pragma code
 
void main (void)
{
    initialiseADConverter();
}
 
/**
 * Intitialises the A/D converter, and waits until the A/D converter has finished enabling.
 * Postcondition: The A/D converter is enabled.
 */
void initialiseADConverter()
{
    ADCON0 = 0b01000001; //Fosc/8, A/D enabled
    ADCON1 = 0b10001110; //Right justify, 1 analog channel; VDD and VSS references
    T0CON  = 0b11000111; //TMR0 prescaler, 1:256
    while(INTCONbits.TMR0IF == 0);
    INTCONbits.TMR0IF = 0;
}
 
/**
 * Returns an unsigned 16 bit integer, containing 10 bits of A/D result. The 6 most
 * significant bits will be 0.
 * Precondition: The A/D Converter is on and initialised
 * @return 10 bit A/D result
 */
unsigned int getADValue()
{
    ADCON0bits.GO = 1;    //Start A/D conversion
    while(PIR1bits.ADIF == 0);    //Wait until ready
 
    int result = ADRESH << 8;    //Get upper two bits
    result = result | ADRESL;    //Get lower eight bits
    return result;                //Result is 10 bits
}
 
/**
 * Converts a mass from one unit to another.
 * Uses the #define conventions of masses, that is, GRAMS = 0,
 * and OUNCES = 1.
 * Usage example:
 * ounceValue = convertUnit(gramValue, GRAMS, OUNCES);
 * @param mass The input mass
 * @param inputUnit A numerical char representing the input mass type
 * @param outputUnit A numerical char represeting the output mass type
 * @return float The converted mass.
 */
float convert_unit(float mass, char inputUnit, char outputUnit)
{
    return mass * massConvertLookup[inputUnit][outputUnit];
}
 
/**
 * Use two points, and simple maths, to work out a calibration line. We need to work out if it's computationally
 * feasible to do it with more points.
 */
void calibrate(unsigned int zeroVoltage, unsigned int secondVoltage, unsigned in secondMass, char massUnit)
{
    float gradient = secondMass / (secondVoltage - zeroVoltage);
    float yIntercept = - zeroVoltage / gradient;
 
    voltageToMassEquation[massUnit] = {gradient, yIntercept};
 
    char otherMassUnit = massUnit ^ 1;    //0 or 1
    voltageToMassEquation[otherMassUnit] = {convert_unit(gradient, massUnit, otherMassUnit), convert_unit(yIntercept, massUnit, otherMassUnit)};
}